package com.rainwen.shiro.service;

import com.rainwen.shiro.entity.SysUser;
import com.rainwen.shiro.entity.SysUserExample;
import com.rainwen.shiro.entity.SysUserRoleExample;
import com.rainwen.shiro.enums.UserStatus;
import com.rainwen.shiro.mapper.SysRoleResourceMapper;
import com.rainwen.shiro.mapper.SysUserMapper;
import com.rainwen.shiro.mapper.SysUserRoleMapper;
import com.rainwen.shiro.page.PageRequest;
import com.rainwen.shiro.util.PasswordHelper;
import com.rainwen.shiro.vo.UrlPermissionVO;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;

import static com.rainwen.shiro.constant.Constants.SALT_LEN;

/**
 *
 * @author rain.wen
 * @date 2017/8/9
 */
@Service
@Transactional(rollbackFor = RuntimeException.class)
public class SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired
    private SysResourceService sysResourceService;

    @Autowired
    private SysRoleResourceMapper sysRoleResourceMapper;

    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public List<SysUser> findUsers(PageRequest pageRequest) {
        return sysUserMapper.findUsers(pageRequest);
    }

    /**
     * 添加用户
     * @param username
     * @param nickname
     * @param plainPassword
     * @return
     */
    public SysUser addSysUser(String username, String nickname, String plainPassword) {
        //生成新盐
        String salt = RandomStringUtils.randomAlphanumeric(SALT_LEN);
        //加密
        String encryptPassword = PasswordHelper.encryptPassword(plainPassword, salt);

        SysUser sysUser = new SysUser();
        sysUser.setUsername(username);
        sysUser.setNickname(nickname);
        sysUser.setPassword(encryptPassword);
        sysUser.setSalt(salt);
        sysUser.setStatus(UserStatus.NORMAL.getValue());
        sysUserMapper.insertSelective(sysUser);
        return sysUser;
    }

    /**
     * 添加用户
     *
     * @param sysUser
     * @return
     */
    public SysUser addSysUser(SysUser sysUser) {
        sysUserMapper.insertSelective(sysUser);
        return sysUser;
    }

    /**
     * 修改密码
     *
     * @param id
     * @param newPassword
     */
    public int changePassword(Integer id, String newPassword) {
        //生成新盐
        String newSalt = RandomStringUtils.randomAlphanumeric(SALT_LEN);
        //加密
        String encryptPassword = PasswordHelper.encryptPassword(newPassword, newSalt);
        return sysUserMapper.changePassword(id, encryptPassword, newSalt);
    }

    /**
     * 添加用户-角色关系
     *
     * @param id
     * @param roleIds
     */
    public int addUserRoles(Integer id, List<Integer> roleIds) {
        return sysUserRoleMapper.batchInsert(id, roleIds);
    }

    /**
     * 移除用户-角色关系
     *
     * @param userId
     * @param roleIds
     */
    public int deleteUserRoles(Integer userId, List<Integer> roleIds) {
        SysUserRoleExample example = new SysUserRoleExample();
        example.createCriteria().andSysUserIdEqualTo(userId).andSysRoleIdIn(roleIds);
        return sysUserRoleMapper.deleteByExample(example);
    }

    /**
     * 根据用户名查找用户
     * @param username
     * @return
     */
    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public SysUser findByUsername(String username) {
        SysUserExample example = new SysUserExample();
        example.createCriteria().andUsernameEqualTo(username);
        List<SysUser> sysUserList = sysUserMapper.selectByExample(example);
        if(CollectionUtils.isEmpty(sysUserList)) {
            return null;
        }
        return CollectionUtils.isEmpty(sysUserList) ? null : sysUserList.get(0);
    }

    /**
     * 根据用户名查所有角色
     *
     * @param username
     * @return
     */
    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public Set<String> findRoles(String username) {
        SysUser sysUser = findByUsername(username);
        if(sysUser == null) {
            return null;
        }
        return sysUserMapper.findRoleNames(sysUser.getId());
    }

    /**
     * 根据用户名查找其资源权限
     * system:user:create,delete,update,view
     *
     * @param username
     * @return
     */
    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public Set<String> findResourcePermissions(String username) {
        //获取拥有的角色Id集合
        List<Integer> roleIds = findRoleIds(username);
        if(CollectionUtils.isEmpty(roleIds)) {
            return null;
        }
        //获取拥有的资源Id集合
        Set<Integer> resourceIds = sysRoleResourceMapper.findResourceIds(StringUtils.join(roleIds, ","));

        return sysResourceService.findResourcePermissions(resourceIds);
    }

    /**
     * 根据用户名查找其资源权限
     * system:user:create,delete,update,view
     *
     * @param username
     * @return
     */
    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public List<UrlPermissionVO> findUrlPermissions(String username) {
        List<Integer> roleIds = findRoleIds(username);
        if(CollectionUtils.isEmpty(roleIds)) {
            return null;
        }
        //获取拥有的资源Id集合
        Set<Integer> resourceIds = sysRoleResourceMapper.findResourceIds(StringUtils.join(roleIds, ","));

        return sysResourceService.findUrlPermissions(resourceIds);
    }

    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public List<Integer> findRoleIds(String username) {
        SysUser sysUser = findByUsername(username);
        if(sysUser == null) {
            return null;
        }
        //获取拥有的角色Id集合
        return sysUserMapper.findRoleIds(sysUser.getId());
    }

    @Transactional(readOnly = true, rollbackFor = RuntimeException.class)
    public List<Integer> findRoleIds(Integer userId) {
        SysUser sysUser = sysUserMapper.selectByPrimaryKey(userId);
        if(sysUser == null) {
            return null;
        }
        //获取拥有的角色Id集合
        return sysUserMapper.findRoleIds(sysUser.getId());
    }
}
